/**
 * IndexedDB 封装类
 * 提供现代化的 IndexedDB 操作接口
 */
export class IndexedStore {
  constructor(dbName = 'ShareTopDB', version = 1, storeName = 'keyValueStore') {
    this.dbName = dbName;
    this.version = version;
    this.storeName = storeName;
    this.db = null;
    this.isInitialized = false;
    this.initPromise = null;
    this.isAsync = true; // IndexedDB 是异步的
  }

  /**
   * 初始化数据库
   * @returns {Promise<IDBDatabase>}
   */
  async init() {
    if (this.isInitialized && this.db) {
      return this.db;
    }

    if (this.initPromise) {
      return this.initPromise;
    }

    this.initPromise = new Promise((resolve, reject) => {
      if (!window.indexedDB) {
        reject(new Error('IndexedDB is not supported in this browser'));
        return;
      }

      const request = indexedDB.open(this.dbName, this.version);

      request.onerror = () => {
        reject(new Error(`Failed to open database: ${request.error}`));
      };

      request.onsuccess = () => {
        this.db = request.result;
        this.isInitialized = true;
        resolve(this.db);
      };

      request.onupgradeneeded = (event) => {
        const db = event.target.result;
        
        // 创建对象存储空间
        if (!db.objectStoreNames.contains(this.storeName)) {
          const store = db.createObjectStore(this.storeName, { keyPath: 'key' });
          
          // 创建索引
          store.createIndex('timestamp', 'timestamp', { unique: false });
          store.createIndex('expires', 'expires', { unique: false });
        }
      };
    });

    return this.initPromise;
  }

  /**
   * 确保数据库已初始化
   * @private
   */
  async ensureInitialized() {
    if (!this.isInitialized) {
      await this.init();
    }
  }

  /**
   * 设置值
   * @param {string} key 键名
   * @param {any} value 值
   * @param {Object} options 选项
   * @param {number} options.expires 过期时间（毫秒）
   * @returns {Promise<boolean>}
   */
  async set(key, value, options = {}) {
    try {
      await this.ensureInitialized();
      
      const now = Date.now();
      const expires = options.expires ? now + options.expires : null;
      
      const item = {
        key,
        value,
        timestamp: now,
        expires
      };

      return new Promise((resolve, reject) => {
        const transaction = this.db.transaction([this.storeName], 'readwrite');
        const store = transaction.objectStore(this.storeName);
        const request = store.put(item);

        request.onsuccess = () => resolve(true);
        request.onerror = () => reject(new Error(`Failed to set key "${key}": ${request.error}`));
      });
    } catch (error) {
      console.error('IndexedStore.set error:', error);
      return false;
    }
  }

  /**
   * 获取值
   * @param {string} key 键名
   * @param {any} defaultValue 默认值
   * @returns {Promise<any>}
   */
  async get(key, defaultValue = null) {
    try {
      await this.ensureInitialized();

      return new Promise((resolve, reject) => {
        const transaction = this.db.transaction([this.storeName], 'readonly');
        const store = transaction.objectStore(this.storeName);
        const request = store.get(key);

        request.onsuccess = () => {
          const result = request.result;
          
          if (!result) {
            resolve(defaultValue);
            return;
          }

          // 检查是否过期
          if (result.expires && Date.now() > result.expires) {
            // 异步删除过期数据
            this.remove(key).catch(console.error);
            resolve(defaultValue);
            return;
          }

          resolve(result.value);
        };

        request.onerror = () => {
          console.error(`Failed to get key "${key}": ${request.error}`);
          resolve(defaultValue);
        };
      });
    } catch (error) {
      console.error('IndexedStore.get error:', error);
      return defaultValue;
    }
  }

  /**
   * 删除值
   * @param {string} key 键名
   * @returns {Promise<boolean>}
   */
  async remove(key) {
    try {
      await this.ensureInitialized();

      return new Promise((resolve, reject) => {
        const transaction = this.db.transaction([this.storeName], 'readwrite');
        const store = transaction.objectStore(this.storeName);
        const request = store.delete(key);

        request.onsuccess = () => resolve(true);
        request.onerror = () => {
          console.error(`Failed to remove key "${key}": ${request.error}`);
          resolve(false);
        };
      });
    } catch (error) {
      console.error('IndexedStore.remove error:', error);
      return false;
    }
  }

  /**
   * 检查键是否存在
   * @param {string} key 键名
   * @returns {Promise<boolean>}
   */
  async has(key) {
    try {
      await this.ensureInitialized();

      return new Promise((resolve, reject) => {
        const transaction = this.db.transaction([this.storeName], 'readonly');
        const store = transaction.objectStore(this.storeName);
        const request = store.count(key);

        request.onsuccess = () => {
          resolve(request.result > 0);
        };

        request.onerror = () => {
          console.error(`Failed to check key "${key}": ${request.error}`);
          resolve(false);
        };
      });
    } catch (error) {
      console.error('IndexedStore.has error:', error);
      return false;
    }
  }

  /**
   * 获取所有键名
   * @returns {Promise<Array<string>>}
   */
  async keys() {
    try {
      await this.ensureInitialized();

      return new Promise((resolve, reject) => {
        const transaction = this.db.transaction([this.storeName], 'readonly');
        const store = transaction.objectStore(this.storeName);
        const request = store.getAllKeys();

        request.onsuccess = () => resolve(request.result || []);
        request.onerror = () => {
          console.error(`Failed to get keys: ${request.error}`);
          resolve([]);
        };
      });
    } catch (error) {
      console.error('IndexedStore.keys error:', error);
      return [];
    }
  }

  /**
   * 获取所有值
   * @returns {Promise<Array<any>>}
   */
  async values() {
    try {
      await this.ensureInitialized();

      return new Promise((resolve, reject) => {
        const transaction = this.db.transaction([this.storeName], 'readonly');
        const store = transaction.objectStore(this.storeName);
        const request = store.getAll();

        request.onsuccess = () => {
          const results = request.result || [];
          const now = Date.now();
          
          // 过滤过期数据
          const validResults = results.filter(item => {
            if (item.expires && now > item.expires) {
              // 异步删除过期数据
              this.remove(item.key).catch(console.error);
              return false;
            }
            return true;
          });

          resolve(validResults.map(item => item.value));
        };

        request.onerror = () => {
          console.error(`Failed to get values: ${request.error}`);
          resolve([]);
        };
      });
    } catch (error) {
      console.error('IndexedStore.values error:', error);
      return [];
    }
  }

  /**
   * 清空所有数据
   * @returns {Promise<boolean>}
   */
  async clear() {
    try {
      await this.ensureInitialized();

      return new Promise((resolve, reject) => {
        const transaction = this.db.transaction([this.storeName], 'readwrite');
        const store = transaction.objectStore(this.storeName);
        const request = store.clear();

        request.onsuccess = () => resolve(true);
        request.onerror = () => {
          console.error(`Failed to clear store: ${request.error}`);
          resolve(false);
        };
      });
    } catch (error) {
      console.error('IndexedStore.clear error:', error);
      return false;
    }
  }

  /**
   * 批量设置
   * @param {Object} items 键值对对象
   * @param {Object} options 选项
   * @returns {Promise<boolean>}
   */
  async setMany(items, options = {}) {
    try {
      await this.ensureInitialized();

      return new Promise((resolve, reject) => {
        const transaction = this.db.transaction([this.storeName], 'readwrite');
        const store = transaction.objectStore(this.storeName);
        
        const now = Date.now();
        const expires = options.expires ? now + options.expires : null;
        
        let completed = 0;
        let hasError = false;
        const keys = Object.keys(items);

        if (keys.length === 0) {
          resolve(true);
          return;
        }

        keys.forEach(key => {
          const item = {
            key,
            value: items[key],
            timestamp: now,
            expires
          };

          const request = store.put(item);
          
          request.onsuccess = () => {
            completed++;
            if (completed === keys.length && !hasError) {
              resolve(true);
            }
          };

          request.onerror = () => {
            hasError = true;
            console.error(`Failed to set key "${key}": ${request.error}`);
            resolve(false);
          };
        });
      });
    } catch (error) {
      console.error('IndexedStore.setMany error:', error);
      return false;
    }
  }

  /**
   * 批量获取
   * @param {Array<string>} keys 键名数组
   * @returns {Promise<Object>}
   */
  async getMany(keys) {
    try {
      await this.ensureInitialized();

      const results = {};
      
      for (const key of keys) {
        results[key] = await this.get(key);
      }

      return results;
    } catch (error) {
      console.error('IndexedStore.getMany error:', error);
      return {};
    }
  }

  /**
   * 批量删除
   * @param {Array<string>} keys 键名数组
   * @returns {Promise<boolean>}
   */
  async removeMany(keys) {
    try {
      await this.ensureInitialized();

      return new Promise((resolve, reject) => {
        const transaction = this.db.transaction([this.storeName], 'readwrite');
        const store = transaction.objectStore(this.storeName);
        
        let completed = 0;
        let hasError = false;

        if (keys.length === 0) {
          resolve(true);
          return;
        }

        keys.forEach(key => {
          const request = store.delete(key);
          
          request.onsuccess = () => {
            completed++;
            if (completed === keys.length && !hasError) {
              resolve(true);
            }
          };

          request.onerror = () => {
            hasError = true;
            console.error(`Failed to remove key "${key}": ${request.error}`);
            resolve(false);
          };
        });
      });
    } catch (error) {
      console.error('IndexedStore.removeMany error:', error);
      return false;
    }
  }

  /**
   * 清理过期数据
   * @returns {Promise<number>} 清理的数据条数
   */
  async cleanExpired() {
    try {
      await this.ensureInitialized();

      return new Promise((resolve, reject) => {
        const transaction = this.db.transaction([this.storeName], 'readwrite');
        const store = transaction.objectStore(this.storeName);
        const index = store.index('expires');
        
        const now = Date.now();
        let cleanedCount = 0;

        // 获取所有有过期时间的记录
        const request = index.openCursor();

        request.onsuccess = (event) => {
          const cursor = event.target.result;
          
          if (cursor) {
            const item = cursor.value;
            
            if (item.expires && now > item.expires) {
              cursor.delete();
              cleanedCount++;
            }
            
            cursor.continue();
          } else {
            resolve(cleanedCount);
          }
        };

        request.onerror = () => {
          console.error(`Failed to clean expired data: ${request.error}`);
          resolve(0);
        };
      });
    } catch (error) {
      console.error('IndexedStore.cleanExpired error:', error);
      return 0;
    }
  }

  /**
   * 获取存储统计信息
   * @returns {Promise<Object>}
   */
  async getStats() {
    try {
      await this.ensureInitialized();

      const keys = await this.keys();
      const values = await this.values();
      
      return {
        count: keys.length,
        keys: keys,
        size: JSON.stringify(values).length // 估算大小
      };
    } catch (error) {
      console.error('IndexedStore.getStats error:', error);
      return { count: 0, keys: [], size: 0 };
    }
  }

  /**
   * 关闭数据库连接
   */
  close() {
    if (this.db) {
      this.db.close();
      this.db = null;
      this.isInitialized = false;
      this.initPromise = null;
    }
  }

  /**
   * 删除整个数据库
   * @returns {Promise<boolean>}
   */
  async deleteDatabase() {
    try {
      this.close();

      return new Promise((resolve, reject) => {
        const deleteRequest = indexedDB.deleteDB(this.dbName);
        
        deleteRequest.onsuccess = () => resolve(true);
        deleteRequest.onerror = () => {
          console.error(`Failed to delete database: ${deleteRequest.error}`);
          resolve(false);
        };
      });
    } catch (error) {
      console.error('IndexedStore.deleteDatabase error:', error);
      return false;
    }
  }
}

// 创建默认实例
export const indexedStore = new IndexedStore();

export default indexedStore;